package com.cdel.akka.supervisor;

import java.util.concurrent.TimeUnit;

import scala.concurrent.duration.Duration;
import akka.actor.OneForOneStrategy;
import akka.actor.Props;
import akka.actor.SupervisorStrategy;
import akka.actor.UntypedActor;
import akka.actor.SupervisorStrategy.Directive;
import akka.japi.Function;

//监督策略
public class Supervisor extends UntypedActor {

	//定义一个OneForOneStrategy，在这个策略中，运行的actor遇到错误后，在1分钟内进行3次重试，如果超过这个频率，那么就会直接杀死actor。具体策略由
	//下面的if语句判断：当遇到ArithmeticException时，继续执行这个actor，不做任何处理；当遇到空指针时，进行actor重启；当遇到IllegalArgumentException
	//时，则直接停止actor。对于这个函数中没有涉及的异常，直接向上抛出，由更顶层的actor处理。
	private static SupervisorStrategy strategy = new OneForOneStrategy(3, Duration.create(1, TimeUnit.MINUTES), new Function<Throwable, Directive>() {

		@Override
		public Directive apply(Throwable t) throws Exception {
			if(t instanceof ArithmeticException){
				System.out.println("meet ArithmeticException, just resume");
				return SupervisorStrategy.resume();
			}else if(t instanceof NullPointerException){
				System.out.println("meet NullPointerException, restart");
				return SupervisorStrategy.restart();
			}else if(t instanceof IllegalArgumentException){
				return SupervisorStrategy.stop();
			}else{
				return SupervisorStrategy.escalate();
			}
		}
	});

	//覆盖默认策略，使用自定义策略
	@Override
	public SupervisorStrategy supervisorStrategy(){
		return strategy;
	}

	//创建一个名为restartActor的子actor，这个子actor就由当前的Supervisor进行监督，当Supervisor接收到一个Props对象时，就会根据这个Props配置生成一个restartActor。
	@Override
	public void onReceive(Object o) throws Throwable {
		if(o instanceof Props){
			getContext().actorOf((Props)o, "restartActor");
		}else{
			unhandled(o);
		}
	}


}
